package com.openluat.LuatTestServer.controller;

import com.openluat.LuatTestServer.pojo.ResponseInfo;
import com.openluat.LuatTestServer.utils.Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;

@RestController
@Slf4j
public class BreakDownloadController {

    @GetMapping("/download")
    public ResponseEntity<String> staticFileServer() {
        File staticFileDir = new File("static");
        if (!staticFileDir.exists()) {
            boolean mkdirRes = staticFileDir.mkdirs();
            if (mkdirRes) {
                log.info("创建static文件夹成功");
            } else {
                String msg = "创建static文件夹失败";
                log.error(msg);
                return ResponseEntity.internalServerError().body(msg);
            }
        }
        String[] fileList = staticFileDir.list();
        if (fileList != null && fileList.length > 0) {
            StringBuilder fileNameList = new StringBuilder();
            fileNameList.append("<script src=\"jquery-3.6.0.min.js\"></script>");
            fileNameList.append("<script type=\"text/javascript\">\n" +
                    "    window.onload = function () {\n" +
                    "        $('#uploadBtn').on(\"click\", function () {\n" +
                    "            var files = $('#fileSelect').prop('files');\n" +
                    "\n" +
                    "            var data = new FormData();\n" +
                    "            data.append('uploadFile', files[0]);\n" +
                    "\n" +
                    "            $.ajax({\n" +
                    "                url: 'http://airtest.openluat.com:2900/uploadFileToStatic',\n" +
                    "                method: 'POST',\n" +
                    "                data: data,\n" +
                    "                contentType: false,\n" +
                    "                processData: false,\n" +
                    "                success: function (res) {\n" +
                    "                    console.log(res)\n" +
                    "                    alert(\"上传成功\")\n" +
                    "                    location.reload(true)\n" +
                    "                }\n" +
                    "            })\n" +
                    "        })\n" +
                    "    }\n" +
                    "</script>");
            fileNameList.append("<input id=\"fileSelect\" name=\"fileSelect\" type='file'>\n" +
                    "    <input id=\"uploadBtn\" type=\"button\" value=\"上传\"><br>");
            for (String fileName : fileList) {
                fileNameList.append("<a href=\"/download/").append(fileName).append("\">").append(fileName).append("</a><br>");
            }
            return ResponseEntity.ok("Files: <br>" + fileNameList);
        } else {
            StringBuffer buffer = new StringBuffer();
            buffer.append("<script src=\"jquery-3.6.0.min.js\"></script>");
            buffer.append("<script type=\"text/javascript\">\n" +
                    "    window.onload = function () {\n" +
                    "        $('#uploadBtn').on(\"click\", function () {\n" +
                    "            var files = $('#fileSelect').prop('files');\n" +
                    "\n" +
                    "            var data = new FormData();\n" +
                    "            data.append('uploadFile', files[0]);\n" +
                    "\n" +
                    "            $.ajax({\n" +
                    "                url: 'http://airtest.openluat.com:2900/uploadFileToStatic',\n" +
                    "                method: 'POST',\n" +
                    "                data: data,\n" +
                    "                contentType: false,\n" +
                    "                processData: false,\n" +
                    "                success: function (res) {\n" +
                    "                    console.log(res)\n" +
                    "                    alert(\"上传成功\")" +
                    "                    location.reload(true)\n" +
                    "                }\n" +
                    "            })\n" +
                    "        })\n" +
                    "    }\n" +
                    "</script>\n");
            buffer.append("<input id=\"fileSelect\" name=\"fileSelect\" type='file'>\n" +
                    "<input id=\"uploadBtn\" type=\"button\" value=\"上传\"><br>");
            buffer.append("Files: <br>No Files\n");

            return ResponseEntity.ok(buffer.toString());
        }
    }

    @GetMapping("/download/{name}")
    public ResponseEntity<ResponseInfo> breakDownload(@PathVariable String name, HttpServletRequest request, HttpServletResponse response) {
        log.info("请求下载文件" + name);
        String fullPath = "static/" + name;
        File downloadFile = new File(fullPath);

        if (!downloadFile.exists()) {
            return new ResponseEntity(new ResponseInfo(404, "找不到文件" + name, new Date()), HttpStatus.NOT_FOUND);
        }

        String md5 = Utils.getFileMD5(downloadFile);

        ServletContext context = request.getServletContext();
        String mimeType = context.getMimeType(fullPath);
        if (mimeType == null) {
            mimeType = "application/octet-stream";
        }

        response.setContentType(mimeType);

        String headerKey = "Content-Disposition";
        String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
        response.setHeader(headerKey, headerValue);
        headerKey = "MD5";
        headerValue = md5;
        response.setHeader(headerKey, headerValue);

        response.setHeader("Accept-Ranges", "bytes");
        long downloadSize = downloadFile.length();
        long fromPos = 0, toPos = 0;
        if (request.getHeader("Range") == null) {
            response.setHeader("Content-Length", downloadSize + "");
        } else {
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            String range = request.getHeader("Range");
            String bytes = range.replaceAll("bytes=", "");
            String[] ary = bytes.split("-");
            fromPos = Long.parseLong(ary[0]);
            if (ary.length == 2) {
                toPos = Long.parseLong(ary[1]);
            }
            int size;
            if (toPos > fromPos) {
                size = (int) (toPos - fromPos) + 1;
            } else {
                size = (int) (downloadSize - fromPos);
            }
            response.setHeader("Content-Length", size + "");
            downloadSize = size;
        }
        RandomAccessFile in = null;
        OutputStream out = null;
        try {
            in = new RandomAccessFile(downloadFile, "rw");
            if (fromPos > 0) {
                in.seek(fromPos);
            }
            int bufLen = (int) (downloadSize < 2048 ? downloadSize : 2048);
            byte[] buffer = new byte[bufLen];
            int num;
            int count = 0;
            out = response.getOutputStream();
            while ((num = in.read(buffer)) != -1) {
                out.write(buffer, 0, num);
                count += num;
                if (downloadSize - count < bufLen) {
                    bufLen = (int) (downloadSize - count);
                    if (bufLen == 0) {
                        break;
                    }
                    buffer = new byte[bufLen];
                }
            }
            response.flushBuffer();
        } catch (IOException e) {
            log.info("数据被暂停或中断。");
        } finally {
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    log.info("数据被暂停或中断。");
                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.info("数据被暂停或中断。");
                }
            }

        }
        return ResponseEntity.ok().build();
    }

}
